#include <stdio.h>
#include <mpi.h>


double function(double x) {
    return x;
}

double trap(double local_a, double local_b, double local_n, double h) {
    double ret = (function(local_a) + function(local_b)) / 2;
    for (int i = 1; i <= (int)(local_n - 1); i++)
    {
        ret += function(local_a + i * h);
    }
    return h * ret;
}

int main() {
    int comm_sz;
    int my_rank;
    double a, b, n, h, local_sum, total_sum = 0;
    double local_n, local_a, local_b;

    MPI_Init(NULL, NULL);
    MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    // printf("fuck %d of %d!!!\n", my_rank, comm_sz);
    if (my_rank == 0)
    {
        printf("Plz input a, b, n!!!\n");
        scanf("%lf %lf %lf", &a, &b, &n);
    }
    MPI_Bcast(&a, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(&b, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(&n, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);

    h = (b - a) / n;
    local_n = n / comm_sz;
    local_a = a + my_rank * local_n * h;
    local_b = local_a + local_n * h;
    local_sum = trap(local_a, local_b, local_n, h);
    MPI_Reduce(&local_sum, &total_sum, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

    if (my_rank == 0)
    {
        // printf("h: %lf, local_a: %lf, local_b: %lf, local_n: %lf, local_sum: %lf\n", h, local_a, local_b, local_n, local_sum);
        printf("The integral of f(x) = x within [%lf, %lf] is approximately %lf\n", a, b, total_sum);
    }

    MPI_Finalize();
    return 0;
}